package com.tbynet.jwp.framework.core;

import com.jfinal.config.*;
import com.jfinal.log.Log;
import com.jfinal.template.Engine;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * JWP框架应用配置基类
 *
 * <p>提供增强的配置生命周期管理、开发环境自动检测、性能监控等功能。
 * 子类只需实现抽象的doConfig*方法即可完成配置。</p>
 *
 * <p><b>主要特性：</b></p>
 * <ul>
 *   <li>线程安全的配置状态管理</li>
 *   <li>详细的配置性能监控和统计</li>
 *   <li>智能的开发/生产环境检测</li>
 *   <li>统一的异常处理和错误报告</li>
 *   <li>可扩展的开发模式特性</li>
 * </ul>
 *
 * @author jwp-framework
 * @version 2.2
 * @since 1.0
 */
public abstract class JwpConfig extends JFinalConfig {

    /** 日志实例 */
    protected final Log log = Log.getLog(this.getClass());

    // ========== 配置常量 ==========

    /** 配置版本号 */
    protected static final String CONFIG_VERSION = "2.2";

    /** 默认插件配置顺序 */
    protected static final int DEFAULT_CONFIG_PLUGIN_ORDER = 1;

    // ========== 状态管理 ==========

    /** 配置启动状态标识（线程安全） */
    private final AtomicBoolean configStarted = new AtomicBoolean(false);

    /** 配置完成状态标识（线程安全） */
    private final AtomicBoolean configCompleted = new AtomicBoolean(false);

    // ========== 性能监控 ==========

    /** 配置开始时间戳 */
    private long configStartTime;

    /** 配置结束时间戳 */
    private long configEndTime;

    /** 配置步骤耗时统计（线程安全） */
    private final Map<String, Long> stepDurations = new ConcurrentHashMap<>();

    // ========== 环境检测相关常量 ==========

    /** 环境变量键名列表（按优先级排序） */
    private static final String[] ENV_KEYS = {
            "app.env", "APP_ENV",
            "spring.profiles.active", "SPRING_PROFILES_ACTIVE",
            "jwp.env", "JWP_ENV"
    };

    /** 开发环境标识值 */
    private static final String[] DEV_ENV_VALUES = {"dev", "development", "local", "test"};

    /** IDE运行环境检测类 */
    private static final String[] IDE_CLASSES = {
            "com.intellij.rt.execution.application.AppMainV2",
            "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
    };

    /** 开发工具类检测 */
    private static final String[] DEV_TOOL_CLASSES = {
            "org.springframework.boot.devtools.RemoteUrlPropertyExtractor",
            "org.h2.tools.Server",
            "org.flywaydb.core.Flyway",
            "liquibase.integration.spring.SpringLiquibase"
    };

    /** 全局开发模式缓存（双重检查锁定模式） */
    private static volatile Boolean globalDevMode = null;

    /** 异步任务执行器 */
    private final ExecutorService executorService = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(), // 核心线程数
            Runtime.getRuntime().availableProcessors() * 2, // 最大线程数
            60L, TimeUnit.SECONDS, // 空闲线程存活时间
            new LinkedBlockingQueue<>(1024), // 任务队列
            new ThreadFactory() {
                private AtomicInteger count = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "Jwp-Async" + count.getAndIncrement());
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy() // 队列满时让提交者线程执行，避免任务丢失
    );

    // 提供获取线程池的方法
    public ExecutorService executorService() {
        return executorService;
    }

    // ========== 配置步骤性能追踪 ==========

    /**
     * 开始记录配置步骤执行时间
     *
     * @param stepName 配置步骤名称
     */
    private void startStep(String stepName) {
        stepDurations.put(stepName + "_start", System.currentTimeMillis());
    }

    /**
     * 结束配置步骤并计算执行耗时
     *
     * @param stepName 配置步骤名称
     */
    private void endStep(String stepName) {
        Long startTime = stepDurations.get(stepName + "_start");
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            stepDurations.put(stepName + "_duration", duration);
        }
    }

    /**
     * 获取配置步骤执行耗时
     *
     * @param stepName 配置步骤名称
     * @return 执行耗时（毫秒），如果步骤不存在则返回0
     */
    protected long getStepDuration(String stepName) {
        Long duration = stepDurations.get(stepName + "_duration");
        return duration != null ? duration : 0;
    }

    // ========== 增强的生命周期管理 ==========

    /**
     * 配置前置处理 - 增强版本
     * <p>在配置开始前执行，包含环境检测、初始化等工作</p>
     */
    protected void beforeConfig() {
        configStartTime = System.currentTimeMillis();
        log.info("开始应用配置初始化...");
        log.info("配置版本: %s, 运行环境: %s", CONFIG_VERSION, getEnvironmentInfo());

        if (isDevMode()) {
            log.debug("开发模式已启用 - 启用详细日志和热加载");
            initializeDevFeatures();
        }
    }

    /**
     * 开发模式特性初始化
     * <p>子类可以重写此方法来初始化开发模式特有的功能，如：
     * <ul>
     *   <li>热加载配置</li>
     *   <li>调试工具初始化</li>
     *   <li>开发期监控</li>
     * </ul>
     * </p>
     */
    protected void initializeDevFeatures() {
        // 默认实现，子类可以重写以添加特定功能
        log.debug("开发模式特性初始化完成");
    }

    /**
     * 配置后置处理 - 增强版本
     * <p>在配置完成后执行，包含性能统计、配置验证等工作</p>
     */
    protected void afterConfig() {
        configEndTime = System.currentTimeMillis();
        long totalDuration = configEndTime - configStartTime;

        log.info("应用配置初始化完成 - 总耗时: %sms", totalDuration);

        // 开发模式下输出详细性能分析
        if (isDevMode()) {
            logConfigurationSummary();
        }

        // 配置验证
        validateConfiguration();
    }

    /**
     * 配置验证
     * <p>验证配置的完整性和正确性，开发模式下会执行更严格的验证</p>
     */
    protected void validateConfiguration() {
        try {
            // 基础配置状态验证
            if (!configCompleted.get()) {
                log.warn("配置完成状态异常，可能某些配置步骤未正常完成");
            }

            // 开发模式下执行严格验证
            if (isDevMode()) {
                performStrictValidation();
            }
        } catch (Exception e) {
            log.error("配置验证过程中发生异常", e);
        }
    }

    /**
     * 严格验证 - 开发模式专用
     * <p>子类可以重写此方法来实现开发模式下的严格验证逻辑</p>
     */
    protected void performStrictValidation() {
        // 默认实现，子类可以重写以添加特定验证逻辑
        log.debug("开发模式严格验证完成");
    }

    // ========== 核心配置方法（模板方法模式） ==========

    /**
     * 常量配置 - 最终方法确保执行流程
     */
    @Override
    public final void configConstant(Constants constants) {
        // 确保前置处理只执行一次
        if (configStarted.compareAndSet(false, true)) {
            beforeConfig();
        }

        executeWithExceptionHandling("常量配置", () -> {
            startStep("configConstant");

            // 设置基础配置
            constants.setConfigPluginOrder(DEFAULT_CONFIG_PLUGIN_ORDER);
            constants.setDevMode(isDevMode());

            // 开发模式下的额外配置
            if (isDevMode()) {
                configureDevConstants(constants);
            }

            // 调用子类具体实现
            doConfigConstant(constants);

            endStep("configConstant");
        });
    }

    /**
     * 路由配置 - 最终方法确保执行流程
     */
    @Override
    public final void configRoute(Routes routes) {
        executeWithExceptionHandling("路由配置", () -> {
            startStep("configRoute");
            doConfigRoute(routes);
            endStep("configRoute");
        });
    }

    /**
     * 插件配置 - 最终方法确保执行流程
     */
    @Override
    public final void configPlugin(Plugins plugins) {
        executeWithExceptionHandling("插件配置", () -> {
            startStep("configPlugin");
            doConfigPlugin(plugins);
            endStep("configPlugin");
        });
    }

    /**
     * 拦截器配置 - 最终方法确保执行流程
     */
    @Override
    public final void configInterceptor(Interceptors interceptors) {
        executeWithExceptionHandling("拦截器配置", () -> {
            startStep("configInterceptor");
            doConfigInterceptor(interceptors);
            endStep("configInterceptor");
        });
    }

    /**
     * 模板引擎配置 - 最终方法确保执行流程
     */
    @Override
    public final void configEngine(Engine engine) {
        executeWithExceptionHandling("模板引擎配置", () -> {
            startStep("configEngine");
            doConfigEngine(engine);
            endStep("configEngine");
        });
    }

    /**
     * 处理器配置 - 最终方法确保执行流程
     */
    @Override
    public final void configHandler(Handlers handlers) {
        executeWithExceptionHandling("处理器配置", () -> {
            startStep("configHandler");
            doConfigHandler(handlers);
            endStep("configHandler");
        });

        // 确保后置处理只执行一次
        if (configCompleted.compareAndSet(false, true)) {
            afterConfig();
        }
    }

    // ========== 开发模式专用配置方法 ==========

    /**
     * 开发模式常量配置
     * <p>子类可以重写此方法来自定义开发模式下的常量配置，如：</p>
     * <ul>
     *   <li>启用模板热加载</li>
     *   <li>设置开发期日志级别</li>
     *   <li>配置开发工具</li>
     * </ul>
     *
     * @param constants 常量配置对象
     */
    protected void configureDevConstants(Constants constants) {
        // 默认的开发模式配置
        constants.setDevMode(true);
        log.debug("开发模式常量配置已应用");
    }

    // ========== 工具方法 ==========

    /**
     * 带异常处理和性能监控的配置执行
     *
     * @param configName 配置名称（用于日志和错误报告）
     * @param task 配置任务
     */
    private void executeWithExceptionHandling(String configName, ConfigTask task) {
        long startTime = System.currentTimeMillis();
        try {
            log.info("开始%s...", configName);
            task.execute();
            long duration = System.currentTimeMillis() - startTime;
            log.info("%s完成 - 耗时: %sms", configName, duration);
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            String errorMessage = String.format("%s失败 - 已运行: %sms", configName, duration);
            log.error(errorMessage, e);
            throw new ConfigException(errorMessage, e);
        }
    }

    /**
     * 获取环境信息摘要
     *
     * @return 格式化的环境信息字符串
     */
    protected String getEnvironmentInfo() {
        return String.format("环境模式: %s, Java版本: %s, 工作目录: %s, 用户: %s",
                isDevMode() ? "开发" : "生产",
                System.getProperty("java.version"),
                System.getProperty("user.dir"),
                System.getProperty("user.name"));
    }

    /**
     * 输出配置执行摘要（开发模式专用）
     */
    private void logConfigurationSummary() {
        log.debug("=== 配置执行详细摘要 ===");
        log.debug("执行环境: %s", getEnvironmentInfo());
        log.debug("配置版本: %s", CONFIG_VERSION);
        log.debug("运行模式: %s", isDevMode() ? "开发模式" : "生产模式");
        log.debug("总执行时间: %sms", configEndTime - configStartTime);

        // 输出各配置步骤耗时
        stepDurations.forEach((key, value) -> {
            if (key.endsWith("_duration")) {
                String stepName = key.replace("_duration", "");
                log.debug("%s 耗时: %sms", stepName, value);
            }
        });
        log.debug("======================");
    }

    // ========== 环境检测逻辑 ==========

    /**
     * 智能开发模式检测
     *
     * @return 如果是开发环境返回true，否则返回false
     */
    private static boolean detectDevMode() {
        // 1. 检查显式配置（最高优先级）
        String explicitMode = getEnvironmentVariable("jwp.dev.mode");
        if (explicitMode != null) {
            return Boolean.parseBoolean(explicitMode);
        }

        // 2. 检查环境配置
        String envValue = getFirstEnvironmentValue();
        if (envValue != null) {
            return isDevelopmentEnvironment(envValue);
        }

        // 3. 调试模式检测
        if ("true".equalsIgnoreCase(System.getProperty("debug"))) {
            return true;
        }

        // 4. IDE 运行环境检测
        if (isRunningFromIDE()) {
            return true;
        }

        // 5. 开发工具依赖检测
        if (hasDevTools()) {
            return true;
        }

        // 6. 开发期依赖检测
        if (hasDevDependencies()) {
            return true;
        }

        return false;
    }

    /**
     * 检测开发期依赖
     *
     * @return 如果存在开发期依赖返回true
     */
    private static boolean hasDevDependencies() {
        String[] devDependencies = {
                "org.junit",
                "org.mockito",
                "org.powermock",
                "ch.qos.logback"
        };

        for (String dependency : devDependencies) {
            if (isClassPresent(dependency)) {
                return true;
            }
        }
        return false;
    }

    // ========== 应用生命周期管理 ==========

    /**
     * 应用启动完成回调
     */
    @Override
    public void onStart() {
        log.info("应用启动完成 - %s", getConfigInfo());

        // 输出JVM内存信息
        Runtime runtime = Runtime.getRuntime();
        log.info("JVM 内存信息 - 最大: %sMB, 总: %sMB, 空闲: %sMB",
                runtime.maxMemory() / 1024 / 1024,
                runtime.totalMemory() / 1024 / 1024,
                runtime.freeMemory() / 1024 / 1024);

        afterStart();
    }

    /**
     * 应用停止回调
     */
    @Override
    public void onStop() {
        log.info("应用开始停止...");
        // 关闭线程池资源
        JwpExecutor.getInstance().shutdown();
        beforeStop();
        log.info("应用停止完成");
    }

    /**
     * 获取配置信息摘要
     *
     * @return 格式化的配置信息字符串
     */
    public String getConfigInfo() {
        return String.format("JwpConfig [版本: %s, 开发模式: %s, 环境: %s, 总耗时: %sms]",
                CONFIG_VERSION, isDevMode(), getEnvironmentInfo(),
                configEndTime - configStartTime);
    }

    // ========== 环境检测工具方法 ==========

    /**
     * 获取首个有效的环境变量值
     */
    private static String getFirstEnvironmentValue() {
        for (String key : ENV_KEYS) {
            String value = getEnvironmentVariable(key);
            if (value != null) {
                return value;
            }
        }
        return null;
    }

    /**
     * 获取环境变量值（优先系统属性，其次环境变量）
     */
    private static String getEnvironmentVariable(String key) {
        String value = System.getProperty(key);
        return value != null ? value : System.getenv(key);
    }

    /**
     * 判断是否为开发环境
     */
    private static boolean isDevelopmentEnvironment(String env) {
        for (String devValue : DEV_ENV_VALUES) {
            if (devValue.equalsIgnoreCase(env)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检测是否从IDE运行
     */
    private static boolean isRunningFromIDE() {
        for (String className : IDE_CLASSES) {
            if (isClassPresent(className)) {
                return true;
            }
        }

        String command = System.getProperty("sun.java.command", "");
        String lowerCommand = command.toLowerCase();
        return lowerCommand.contains("idea_rt.jar") ||
                lowerCommand.contains("eclipse") ||
                lowerCommand.contains("gradle") ||
                lowerCommand.contains("maven");
    }

    /**
     * 检测是否存在开发工具
     */
    private static boolean hasDevTools() {
        for (String className : DEV_TOOL_CLASSES) {
            if (isClassPresent(className)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检测类是否存在
     */
    private static boolean isClassPresent(String className) {
        try {
            Class.forName(className, false, JwpConfig.class.getClassLoader());
            return true;
        } catch (ClassNotFoundException | NoClassDefFoundError e) {
            return false;
        }
    }

    // ========== 公共访问方法 ==========

    /**
     * 双重检查锁定模式获取开发模式状态
     */
    private static boolean checkGlobalDevMode() {
        if (globalDevMode == null) {
            synchronized (JwpConfig.class) {
                if (globalDevMode == null) {
                    globalDevMode = detectDevMode();
                }
            }
        }
        return globalDevMode;
    }

    /**
     * 判断是否为开发模式
     *
     * @return 如果是开发模式返回true
     */
    protected boolean isDevMode() {
        return checkGlobalDevMode();
    }

    /**
     * 判断是否为生产模式
     *
     * @return 如果是生产模式返回true
     */
    protected boolean isProdMode() {
        return !checkGlobalDevMode();
    }

    /**
     * 应用启动后回调 - 子类可重写
     */
    protected void afterStart() {
        // 默认空实现，子类可以重写
    }

    /**
     * 应用停止前回调 - 子类可重写
     */
    protected void beforeStop() {
        // 默认空实现，子类可以重写
    }

    // ========== 抽象配置方法（子类必须实现） ==========

    /**
     * 配置常量 - 子类具体实现
     */
    protected abstract void doConfigConstant(Constants constants);

    /**
     * 配置路由 - 子类具体实现
     */
    protected abstract void doConfigRoute(Routes routes);

    /**
     * 配置插件 - 子类具体实现
     */
    protected abstract void doConfigPlugin(Plugins plugins);

    /**
     * 配置拦截器 - 子类具体实现
     */
    protected abstract void doConfigInterceptor(Interceptors interceptors);

    /**
     * 配置处理器 - 子类具体实现
     */
    protected abstract void doConfigHandler(Handlers handlers);

    /**
     * 配置模板引擎 - 子类具体实现
     */
    protected abstract void doConfigEngine(Engine engine);

    // ========== 内部类和接口 ==========

    /**
     * 配置异常类
     * <p>封装配置过程中的异常，包含错误发生时间戳</p>
     */
    public static class ConfigException extends RuntimeException {
        private final long errorTime;

        public ConfigException(String message) {
            super(message);
            this.errorTime = System.currentTimeMillis();
        }

        public ConfigException(String message, Throwable cause) {
            super(message, cause);
            this.errorTime = System.currentTimeMillis();
        }

        /**
         * 获取异常发生时间
         */
        public long getErrorTime() {
            return errorTime;
        }
    }

    /**
     * 配置任务函数式接口
     */
    @FunctionalInterface
    private interface ConfigTask {
        /**
         * 执行配置任务
         */
        void execute();
    }
}